package org.jetnuke.modules.blog.utils;

import org.apache.log4j.Logger;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.util.GregorianCalendar;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;

import net.jforum.entities.User;
import net.jforum.util.concurrent.Task;
import net.jforum.util.concurrent.executor.QueuedExecutor;
import net.jforum.util.preferences.ConfigKeys;
import net.jforum.util.preferences.SystemGlobals;

import org.apache.xmlrpc.XmlRpcException;
import org.jetnuke.dao.BlogCategoryDAO;
import org.jetnuke.dao.BlogPostDAO;
import org.jetnuke.dao.DataAccessDriver;
import org.jetnuke.entities.BlogCategory;
import org.jetnuke.entities.BlogPost;
import org.jetnuke.entities.BlogSettings;
import org.jetnuke.entities.MainConfig;
import org.jetnuke.repository.MainConfigRepository;
import org.jetnuke.util.StringUtils;

public class MetaWeblogAPIHandler extends BloggerAPIHandler {
	/**
	 * Logger for this class
	 */
	private static final Logger logger = Logger
			.getLogger(MetaWeblogAPIHandler.class);

	protected static final String API_PREFIX = "metaWeblog";
	protected static final String MEMBER_DESCRIPTION = "description";
	protected static final String MEMBER_TITLE = "title";
	protected static final String MEMBER_PERMALINK = "permaLink";
	protected static final String MEMBER_DATE_CREATED = "dateCreated";
	protected static final String MEMBER_LINK = "link";
	protected static final String MEMBER_POSTID = "postid";
	protected static final String MEMBER_CATEGORIES = "categories";

	public String getName() {
		return API_PREFIX;
	}

	public Object getCategories(String blogid, String userid, String password)
			throws Exception {
		if (logger.isDebugEnabled()) {
			logger.debug("getCategories(String, String, String) - start"); //$NON-NLS-1$
		}

		User user = validate(userid, password);

		try {
			Hashtable result = new Hashtable();
			List cats = DataAccessDriver.getInst().newBlogCategoryDAO()
					.selectByUser(user.getId());
			Iterator it = cats.iterator();
			while (it.hasNext()) {
				BlogCategory bc = (BlogCategory) it.next();
				Hashtable catlist = new Hashtable(3);
				catlist.put(MEMBER_DESCRIPTION, bc.getNAME());
				// catlist.put(MEMBER_HTML_URL, category.getCategoryURL());
				// catlist.put(MEMBER_RSS_URL, category.getCategoryURL() +
				// "?flavor=rss2");

				result.put(String.valueOf(bc.getID()), catlist);
			}

			if (logger.isDebugEnabled()) {
				logger.debug("getCategories(String, String, String) - end"); //$NON-NLS-1$
			}
			return result;
		} catch (Exception e) {
			logger.error("getCategories(String, String, String)", e); //$NON-NLS-1$

			String msg = "ERROR in MetaWeblogAPIHandler.getCategories";

			throw new XmlRpcException(UNKNOWN_EXCEPTION, msg);
		}

	}

	public boolean editPost(String postid, String userid, String password,
			Hashtable struct, boolean publish) throws Exception {
		if (logger.isDebugEnabled()) {
			logger
					.debug("editPost(String, String, String, Hashtable, boolean) - start"); //$NON-NLS-1$
		}

		User user = validate(userid, password);

		Hashtable postcontent = struct;
		String description = (String) postcontent.get(MEMBER_DESCRIPTION);
		String title = (String) postcontent.get(MEMBER_TITLE);
		if (title == null)
			title = "";
		BlogPostDAO bpm = DataAccessDriver.getInst().newBlogPostDAO();
		BlogPost blogPost = bpm.retrieveByPK(Integer.parseInt(postid));
		if (blogPost.getAID() == user.getId()) {
			blogPost.setPOSTTITLE(title);
			blogPost.setPOSTCONTENT(description);
			blogPost.setPOSTMODIFIED(new GregorianCalendar().getTime());
			bpm.update(blogPost);
		}

		if (logger.isDebugEnabled()) {
			logger
					.debug("editPost(String, String, String, Hashtable, boolean) - end"); //$NON-NLS-1$
		}
		return true;
	}

	public String newPost(String blogid, String userid, String password,
			Hashtable struct, boolean publish) throws Exception {
		if (logger.isDebugEnabled()) {
			logger
					.debug("newPost(String, String, String, Hashtable, boolean) - start"); //$NON-NLS-1$
		}

		User user = validate(userid, password);
		Hashtable postcontent = struct;
		String description = (String) postcontent.get(MEMBER_DESCRIPTION);
		String title = (String) postcontent.get(MEMBER_TITLE);
		if (title == null)
			title = "";
		BlogPost bp = new BlogPost();
		BlogCategoryDAO bcm = DataAccessDriver.getInst().newBlogCategoryDAO();
		List categories = bcm.selectByUser(user.getId());
		int category = ((BlogCategory) categories.get(0)).getID();
		bp.setAID(user.getId());
		bp.setCOMMENTSTATUS("open");
		BlogPostDAO bpm = DataAccessDriver.getInst().newBlogPostDAO();
		bp.setPOSTDATE(new GregorianCalendar().getTime());
		bp.setPOSTCATEGORY(category);
		bp.setPOSTCONTENT(description);
		bp.setPOSTEXCERPT("");
		bp.setPOSTPASSWORD("");
		bp.setGUID(" ");
		bp.setPOSTSTATUS("publish");

		bp.setPOSTTITLE(title);
		bp.setPINGSTATUS("open");
		bp.setTOPING("");
		final int id;
		bp.setPINGED("");

		id = bpm.addNew(bp);
		bp.setID(id);

		bp.setID(id);
		bp.setGUID(MainConfigRepository.getMainConfig().getNUKEURL()
				+ "do/blog/show_page?id=" + id);
		bpm.update(bp);

		MainConfig config = MainConfigRepository.getMainConfig();
		final String url = config.getNUKEURL();
		QueuedExecutor.getInstance().execute(new Task() {

			public Object execute() throws Exception {
				if (logger.isDebugEnabled()) {
					logger.debug("$Task.execute() - start"); //$NON-NLS-1$
				}

				try {

					BlogUtils.doTrackback(url, id);
					BlogUtils.doPingback(url, id);
				} catch (Throwable e) {
					logger.error("$Task.execute()", e); //$NON-NLS-1$

					if (logger.isDebugEnabled()) {
						logger.debug("$Task.execute() - end"); //$NON-NLS-1$
					}
					return "FAILURE";
				}

				if (logger.isDebugEnabled()) {
					logger.debug("$Task.execute() - end"); //$NON-NLS-1$
				}
				return "SUCCESS";
			}
		});//

		String returnString = String.valueOf(id);
		if (logger.isDebugEnabled()) {
			logger
					.debug("newPost(String, String, String, Hashtable, boolean) - end"); //$NON-NLS-1$
		}
		return returnString;

	}

	// ------------------------------------------------------------------------

	/**
	 * 
	 * @param postid
	 * @param userid
	 * @param password
	 * @return
	 * @throws Exception
	 */
	public Object getPost(String postid, String userid, String password)
			throws Exception {
		if (logger.isDebugEnabled()) {
			logger.debug("getPost(String, String, String) - start"); //$NON-NLS-1$
		}

		User user = validate(userid, password);
		BlogPostDAO bpd = DataAccessDriver.getInst().newBlogPostDAO();
		try {
			BlogPost entry = bpd.retrieveByPK(Integer.parseInt(postid));
			if (entry.getAID() != user.getId())
				throw new XmlRpcException(AUTHORIZATION_EXCEPTION,
						AUTHORIZATION_EXCEPTION_MSG);
			Hashtable postcontent = new Hashtable(3);
			postcontent.put(MEMBER_TITLE, entry.getPOSTTITLE());
			postcontent.put(MEMBER_LINK, entry.getGUID());
			postcontent.put(MEMBER_DESCRIPTION, entry.getPOSTCONTENT());
			postcontent.put(MEMBER_DATE_CREATED, entry.getPOSTDATE());
			postcontent.put(MEMBER_PERMALINK, entry.getGUID());
			postcontent.put(MEMBER_POSTID, String.valueOf(entry.getID()));

			Vector postCategories = new Vector(1);
			postCategories.add(String.valueOf(entry.getPOSTCATEGORY()));
			postcontent.put(MEMBER_CATEGORIES, postCategories);

			if (logger.isDebugEnabled()) {
				logger.debug("getPost(String, String, String) - end"); //$NON-NLS-1$
			}
			return postcontent;
		} catch (Throwable e) {
			logger.error("getPost(String, String, String)", e); //$NON-NLS-1$

			throw new XmlRpcException(INVALID_POSTID, INVALID_POSTID_MSG);
		}
	}

	public Object newMediaObject(String blogid, String userid, String password,
			Hashtable struct) throws Exception {
		if (logger.isDebugEnabled()) {
			logger
					.debug("newMediaObject(String, String, String, Hashtable) - start"); //$NON-NLS-1$
		}

		User user = validate(userid, password);
		String initPath = SystemGlobals
				.getValue(ConfigKeys.ATTACHMENTS_STORE_DIR)
				+ "/blog/" + user.getId() + "/";
		// String path = sc.getRealPath(initPath);
		File pathDir = new File(initPath);
		if (!pathDir.exists()) {
			pathDir.mkdirs();
		}
		String fileName = (String) struct.get("name");
		String simplifiedName = StringUtils.getSimpleFileName(fileName);
		byte[] bits = (byte[]) struct.get("bits");
		long resourcesSize = getResourcesSize(0, pathDir);
		int fileSize = bits.length;
		BlogSettings bs = DataAccessDriver.getInst().newBlogSettingsDAO().get();
		if (((resourcesSize + fileSize) > 1024 * bs.getLIMIT())) {
			throw new XmlRpcException(UPLOAD_DENIED_EXCEPTION,
					"No available space");
		}

		// "File upload denied because:" + msgs.toString());

		File f = new File(pathDir, simplifiedName);
		OutputStream outputStream = new BufferedOutputStream(
				new FileOutputStream(f));
		outputStream.write(bits);
		outputStream.close();

		Hashtable returnStruct = new Hashtable(1);
		returnStruct.put("url", MainConfigRepository.getMainConfig()
				.getNUKEURL()
				+ "do/blog/get_file?uid="
				+ user.getId()
				+ "&file="
				+ simplifiedName);

		if (logger.isDebugEnabled()) {
			logger
					.debug("newMediaObject(String, String, String, Hashtable) - end"); //$NON-NLS-1$
		}
		return returnStruct;
	}

	private static long getResourcesSize(long initSize, File pathDir) {
		if (logger.isDebugEnabled()) {
			logger.debug("getResourcesSize(long, File) - start"); //$NON-NLS-1$
		}

		File f[] = pathDir.listFiles();
		long ret = initSize;
		for (int i = 0; i < f.length; i++) {
			if (f[i].isFile()) {
				ret = ret + f[i].length();
			} else {
				ret = getResourcesSize(ret, f[i]);
			}
		}

		if (logger.isDebugEnabled()) {
			logger.debug("getResourcesSize(long, File) - end"); //$NON-NLS-1$
		}
		return ret;
	}

	public Object getRecentPosts(String blogid, String userid, String password,
			int numposts) throws Exception {
		if (logger.isDebugEnabled()) {
			logger.debug("getRecentPosts(String, String, String, int) - start"); //$NON-NLS-1$
		}

		// User user =
		validate(userid, password);
		// TODO

		if (logger.isDebugEnabled()) {
			logger.debug("getRecentPosts(String, String, String, int) - end"); //$NON-NLS-1$
		}
		return null;
	}

}
